/**
 * @file Exceptionhandler.h
 * @brief Header file for the Exceptionhandler class.
 *
 * This file contains the declaration of the Exceptionhandler class, which is designed to handle exceptions and errors
 * within a software system. The Exceptionhandler class is implemented as a singleton to ensure a single centralized
 * instance manages all exception handling throughout the application. It provides mechanisms to bind custom handlers
 * for failure signals, retrieve diagnostic information such as stack traces, system and CPU usage, and thread statuses,
 * making it a comprehensive tool for error management and debugging.
 * 
 * The file defines the Exceptionhandler class, including its methods for setting up signal handlers, gathering system
 * and thread information, and processing exceptions. It also includes definitions for auxiliary structures such as
 * FailureSignal_t for representing failure signals and ThreadInfo for holding thread information.
 *
 * The Exceptionhandler class offers a detailed approach to capturing, analyzing, and reporting errors, facilitating
 * easier diagnosis and resolution of issues within the application. It is crucial for developers looking to implement
 * robust error handling and diagnostic capabilities in their software.
 *
 * Usage examples and further implementation details can be found within the class documentation, providing a clear
 * guide on integrating the Exceptionhandler into software projects.
 *
 * @author liuzhiyu (liuzhiyu27@foxmail.com)
 * @copyright Copyright (c) 2023 by liuzhiyu, All Rights Reserved.
 */
#ifndef SIGNAL_HANDLER_LINUX_H
#define SIGNAL_HANDLER_LINUX_H
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
#include <csignal>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <functional>
#include <array>
#include <vector>

namespace errors{
/**
 * @struct FailureSignal_t
 * @brief Represents a failure signal with a number and a name.
 */
typedef struct{
    int number;          ///< Signal number.
    const std::string name; ///< Signal name.
} FailureSignal_t;

/**
 * @struct ThreadInfo
 * @brief Contains information about a thread.
 */
struct ThreadInfo {
    int tid;            ///< Thread ID.
    std::string comm;   ///< Thread name.
    char state;         ///< Thread state.
};

/**
 * @class Exceptionhandler
 * @brief Handles exceptions and gathers system and thread information for diagnostics.
 *
 * The Exceptionhandler class is designed to capture and process detailed information
 * about exceptions or errors that occur within a software system. It is implemented
 * as a singleton, ensuring that only one instance of the class is created and used
 * throughout the application. This design pattern is suitable for handling exceptions
 * as it provides a centralized mechanism for error management.
 *
 * The class provides functionalities to bind custom handlers for failure signals,
 * gather stack traces, retrieve system information, monitor CPU and resource usage,
 * and inspect the status of threads within the process. This makes it an essential tool
 * for both debugging and post-mortem analysis.
 *
 * The class also includes a nested struct, `ExceptionResult`, which is used to store
 * detailed information about an exception, including stack traces, system info, CPU usage,
 * and thread statuses.
 *
 * Usage:
 * To use the Exceptionhandler, one should obtain the singleton instance and then
 * invoke its methods as needed to handle exceptions or retrieve diagnostic information.
 * It is important to note that as the class is designed with the singleton pattern,
 * copying and assignment operations are deleted to prevent multiple instances.
 *
 * Example:
 * ```
 * Exceptionhandler& handler = Exceptionhandler::get_instance();
 * handler.bindingFailureSignalHandler(customSignalHandler);
 * Exceptionhandler::ExceptionResult result;
 * if (handler.getAllInfo(result)) {
 *     // Process exception result...
 * }
 * ```
 *
 * The class also supports the direct retrieval of diagnostic information as a string,
 * which can be useful for logging or displaying error information.
 */
class Exceptionhandler {
public:
    /**
     * @struct ExceptionResult
     * @brief Holds detailed information about an exception.
     */
    struct ExceptionResult {
        std::vector<std::string> stackTrace; ///< Stack trace of the exception.
        std::string sysinfo;                 ///< System information.
        std::string cpuUsageInfo;            ///< CPU usage information.
        std::vector<std::string> resourceUsage; ///< Resource usage information.
        std::vector<ThreadInfo> threadStatus; ///< Status of threads.
    };
  // Copy constructor and assignment operator are deleted to enforce singleton pattern.
  Exceptionhandler(const Exceptionhandler&)=delete;
	Exceptionhandler& operator=(const Exceptionhandler&)=delete;
    /**
     * @brief Destructor for Exceptionhandler.
     */
    ~Exceptionhandler();
    /**
     * @brief Get the singleton instance of Exceptionhandler.
     * @return Reference to the singleton instance.
     */
	static Exceptionhandler& get_instance(){
	  static Exceptionhandler instance;
		return instance;
	}
    /**
     * @brief Static array of known failure signals.
     */
    static std::array<FailureSignal_t, 10> kFailureSignals;

    /**
     * @brief Binds a function to handle failure signals.
     * @param handler Function to handle failure signals.
     */
    void bindingFailureSignalHandler(std::function<void(int, siginfo_t *, void *)> handler);

    /**
     * @brief Retrieves the stack trace of the current thread.
     * @param stackTrace Reference to a vector to store the stack trace.
     * @param skip Number of stack frames to skip from the top.
     */
    void getStackTrace(std::vector<std::string> &stackTrace, int skip = 0);

    /**
     * @brief Gets system information.
     * @param sysinfo Reference to a string to store system information.
     * @return True if successful, false otherwise.
     */
    bool getSysinfo(std::string &sysinfo);

    /**
     * @brief Gets CPU usage information of the process.
     * @param cpuUsageInfo Reference to a string to store CPU usage information.
     * @return True if successful, false otherwise.
     */
    bool getProcessCPUUsage(std::string &cpuUsageInfo);

    /**
     * @brief Gets resource usage information of the process.
     * @param result Reference to a vector to store resource usage information.
     * @return True if successful, false otherwise.
     */
    bool getProcessResourceUsage(std::vector<std::string>& result);

    /**
     * @brief Gets the status of all threads in the process.
     * @param threadStatus Reference to a vector to store thread status information.
     * @return True if successful, false otherwise.
     */
    bool getThreadStatus(std::vector<ThreadInfo>& threadStatus);

    /**
     * @brief Gathers all exception-related information.
     * @param result Reference to ExceptionResult to store the gathered information.
     * @return True if successful, false otherwise.
     */
    bool getAllInfo(ExceptionResult& result);

    /**
     * @brief Gathers all exception-related information and returns it as a string.
     * @return A string containing all gathered information.
     */
    std::string getAllInfo();

private:
    /**
     * @brief Private constructor for the Exceptionhandler singleton.
     */
    Exceptionhandler();

    /**
     * @brief Static method to handle failure signals.
     * @param signum The signal number.
     * @param signal_info Pointer to siginfo_t structure providing additional signal information.
     * @param ucontext Pointer to the context in which the signal was received.
     */
    static void staticFailureSignalHandler(int signum, siginfo_t *signal_info, void *ucontext);

    /**
     * @brief Static function pointer for a custom handler function.
     * 
     * This function is invoked when a failure signal is received.
     */
    static std::function<void(int, siginfo_t *, void *)> _handler;
};

}
#endif // SIGNAL_HANDLER_LINUX_H